#include "VBO.h"
#include <stdio.h>

VBO::VBO()
{
	// set vbo id 0 to intinal
	vertexVBOId = 0;
	indexVBOId = 0;
	normalVBOId = 0;
	colorVBOId = 0;

	vertices = 0;
	indices = 0;
	normals = 0;
	colors = 0;
}	

VBO::~VBO()
{
	if(vertices != 0)
		delete vertices;
	if(indices != 0)
		delete indices;
	if (normals != 0)
		delete normals;
	if (colors != 0)
		delete colors;

	glDeleteBuffers(1, &vertexVBOId);
	glDeleteBuffers(1, &indexVBOId);
	glDeleteBuffers(1, &normalVBOId);
	glDeleteBuffers(1, &colorVBOId);
}

void VBO::init(GLfloat* v, GLfloat* n, GLfloat* c, GLuint *i, int nv, int ni)
{
	vertices = v;
	normals = n;
	colors = c;
	indices = i;
	numIndices = ni;

	vertexVBOId = createVBO(vertices, sizeof(GLfloat)*ni*3, GL_ARRAY_BUFFER, GL_STATIC_DRAW);
	normalVBOId = createVBO(normals, sizeof(GLfloat)*ni*3, GL_ARRAY_BUFFER, GL_STATIC_DRAW);
	colorVBOId = createVBO(colors, sizeof(GLfloat)*ni*3, GL_ARRAY_BUFFER, GL_STATIC_DRAW);
	//indexVBOId = createVBO(indices, sizeof(GLuint)*ni, GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW);
}

void VBO::draw()
{
	glBindBuffer(GL_ARRAY_BUFFER, vertexVBOId);
	glEnableClientState(GL_VERTEX_ARRAY);
	glVertexPointer(3, GL_FLOAT, 0, 0);

	glBindBuffer(GL_ARRAY_BUFFER, normalVBOId);
	glEnableClientState(GL_NORMAL_ARRAY);
	glNormalPointer(GL_FLOAT, 0, 0);

	glBindBuffer(GL_ARRAY_BUFFER, colorVBOId);
	glEnableClientState(GL_COLOR_ARRAY);
	glColorPointer(3, GL_FLOAT, 0, 0);

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexVBOId);
	glIndexPointer(GL_UNSIGNED_INT, 0, 0);

	// This is the actual draw command
	// glDrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_INT, 0);
	glDrawArrays(GL_TRIANGLES, 0, numIndices);
	glDisableClientState(GL_VERTEX_ARRAY);
	glDisableClientState(GL_NORMAL_ARRAY);
	glDisableClientState(GL_COLOR_ARRAY);
}

///////////////////////////////////////////////////////////////////////////////
// generate vertex buffer object and bind it with its data
// You must give 2 hints about data usage; target and mode, so that OpenGL can
// decide which data should be stored and its location.
// VBO works with 2 different targets; GL_ARRAY_BUFFER for vertex arrays
// and GL_ELEMENT_ARRAY_BUFFER for index array in glDrawElements().
// The default target is GL_ARRAY_BUFFER.
// By default, usage mode is set as GL_STATIC_DRAW.
// Other usages are GL_STREAM_DRAW, GL_STREAM_READ, GL_STREAM_COPY,
// GL_STATIC_DRAW, GL_STATIC_READ, GL_STATIC_COPY,
// GL_DYNAMIC_DRAW, GL_DYNAMIC_READ, GL_DYNAMIC_COPY.
///////////////////////////////////////////////////////////////////////////////
GLuint VBO::createVBO(const void* data, int dataSize, GLenum target, GLenum usage)
{
	GLuint id = 0;  // 0 is reserved, glGenBuffers() will return non-zero id if success

	glGenBuffers(1, &id);                        // create a vbo
	glBindBuffer(target, id);                    // activate vbo id to use
	glBufferData(target, dataSize, data, usage); // upload data to video card

	// check data size in VBO is same as input array, if not return 0 and delete VBO
	int bufferSize = 0;
	glGetBufferParameteriv(target, GL_BUFFER_SIZE, &bufferSize);
	printf("buffer size is %i \n", bufferSize);
	if(dataSize != bufferSize)
	{
		glDeleteBuffersARB(1, &id);
		id = 0;
		//std::cout << "[createVBO()] Data size is mismatch with input array\n";
	}

	return id;      // return VBO id
}